package com.lyl.pipeline.core;

import com.lyl.pipeline.annotation.PipeNode;
import com.lyl.pipeline.annotation.Pipeline;
import com.lyl.pipeline.handler.BasePipeNodeHandler;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.aspectj.lang.ProceedingJoinPoint;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Optional;

/**
 * @author Mr.Luo
 * @date 2022-07-27 17:16
 * @desc 流水线上下文
 */
@Data
@AllArgsConstructor
public class PipelineContext {
    /**
     * aop连接点
     */
    private ProceedingJoinPoint joinPoint;

    /**
     * 注解
     */
    private final Pipeline pipeline;

    /**
     * 处理器Map
     */
    private final Map<String, BasePipeNodeHandler> handlerMap;

    /**
     * 节点迭代器
     */
    private final PipeNodeIterator pipeNodeIterator = new PipeNodeIterator();

    /**
     * 存储上下文所需要的数据
     */
    private final Map<String, Object> contextDataMap = new HashMap<>();

    /**
     * 开始执行责任链(有参)
     *
     * @param obj 需要在责任链中传递的参数
     * @return 执行结果
     */
    public Object execute(Object obj) {
        return next(obj);
    }

    /**
     * 开始执行责任链(无参)
     *
     * @return 执行结果
     */
    public Object execute() {
        return next(null);
    }

    /**
     * 执行下一个步骤(无参)
     *
     * @return 执行结果
     */
    public Object next() {
        return next(null);
    }

    /**
     * 执行下一个步骤(有参)
     *
     * @param obj 传递的参数
     * @return 执行结果
     */
    public Object next(Object obj) {
        if (pipeNodeIterator.hasNext()) {
            PipeNode pipeNode = pipeNodeIterator.next();
            assert pipeNode != null;
            BasePipeNodeHandler handler = Optional.ofNullable(handlerMap.get(pipeNode.value())).orElseThrow(() -> new RuntimeException("找不到对应的处理器"));
            return handler.invoke(obj, pipeNode, this);
        }
        return null;
    }

    /**
     * PipeNode迭代器
     */
    private class PipeNodeIterator implements Iterator<PipeNode> {
        int index = 0;

        /**
         * 是否有下一个节点
         *
         * @return true/false
         */
        @Override
        public boolean hasNext() {
            return index < pipeline.value().length;
        }

        /**
         * 下一个节点
         *
         * @return PipeNode
         */
        @Override
        public PipeNode next() {
            return hasNext() ? pipeline.value()[index++] : null;
        }
    }

    public static PipelineContextBuilder builder() {
        return new PipelineContextBuilder();
    }

    public static PipelineContextBuilder builder(Pipeline pipeline, Map<String, BasePipeNodeHandler> handlerMap) {
        return new PipelineContextBuilder(null, pipeline, handlerMap);
    }

    public static PipelineContextBuilder builder(ProceedingJoinPoint joinPoint, Pipeline pipeline, Map<String, BasePipeNodeHandler> handlerMap) {
        return new PipelineContextBuilder(joinPoint, pipeline, handlerMap);
    }

    @Data
    @NoArgsConstructor
    @AllArgsConstructor
    public static class PipelineContextBuilder {
        /**
         * aop连接点
         */
        private ProceedingJoinPoint joinPoint;

        /**
         * 注解
         */
        private Pipeline pipeline;

        /**
         * 处理器Map
         */
        private Map<String, BasePipeNodeHandler> handlerMap;

        public PipelineContextBuilder joinPoint(ProceedingJoinPoint joinPoint) {
            this.joinPoint = joinPoint;
            return this;
        }

        public PipelineContextBuilder pipeline(Pipeline pipeline) {
            this.pipeline = pipeline;
            return this;
        }

        public PipelineContextBuilder handlerMap(Map<String, BasePipeNodeHandler> handlerMap) {
            this.handlerMap = handlerMap;
            return this;
        }

        public PipelineContext build() {
            return new PipelineContext(this.joinPoint, this.pipeline, this.handlerMap);
        }
    }
}
